package com.dimples.wxpush.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.dimples.wxpush.constant.ConfigConstant;
import com.dimples.wxpush.entity.QyWxImageTextMessage;
import com.dimples.wxpush.entity.TextMessage;
import com.dimples.wxpush.enums.BirthdateEnum;
import com.dimples.wxpush.enums.QyWxClickEnum;
import com.dimples.wxpush.helper.QyWxHelper;
import com.dimples.wxpush.helper.WxHelper;
import com.dimples.wxpush.model.bo.WeatherHourlyBO;
import com.dimples.wxpush.model.bo.WeatherNowBO;
import com.dimples.wxpush.model.bo.WeatherThreeDayBO;
import com.dimples.wxpush.service.ProverbService;
import com.dimples.wxpush.service.SendService;
import com.dimples.wxpush.service.TianqiService;
import com.alibaba.fastjson.JSONObject;
import com.dimples.wxpush.utils.*;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: wenqiaogang
 * @DateTime: 2022/8/23 17:35
 * @Description: TODO
 */
@Service
@RequiredArgsConstructor
public class SendServiceImpl implements SendService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final TianqiService tianqiService;
    private final ProverbService proverbService;
    private final ConfigConstant configConstant;
    private final QyWxHelper qyWxHelper;
    private final WxHelper wxHelper;

    private String getAccessToken() {
        //这里直接写死就可以，不用改，用法可以去看api
        String grant_type = "client_credential";
        //封装请求数据
        String params = "grant_type=" + grant_type + "&secret=" + configConstant.getAppSecret() + "&appid=" + configConstant.getAppId();
        //发送GET请求
        String sendGet = HttpUtils.sendGet("https://api.weixin.qq.com/cgi-bin/token", params);
        // 解析相应内容（转换成json对象）
        JSONObject jsonObject1 = JSONObject.parseObject(sendGet);
        logger.info("微信token响应结果=" + jsonObject1);
        //拿到accesstoken
        return (String) jsonObject1.get("access_token");
    }

    /**
     * 填充微信模板中的信息
     *
     * @return
     */
    @Override
    public String sendWeChatMsg() {
        String accessToken = getAccessToken();
        if (!StringUtils.hasText(accessToken)) {
            String errorMsg = "token获取失败，请检查：公众号的，appId、appSecret是否输入正确，务必重刷浏览器重新复制";
            logger.error(errorMsg);
            return errorMsg;
        }
        List<JSONObject> errorList = new ArrayList<>();
        HashMap<String, Object> resultMap = new HashMap<>();
        JSONObject templateMsg = new JSONObject();
        //遍历用户的ID，保证每个用户都收到推送
        for (String opedId : configConstant.getOpenidList()) {

            //今天
            String date = DateUtil.formatDate(new Date());
            String week = DateUtil.dayOfWeekEnum(new Date()).toChinese();
            String day = date + " " + week;
            JSONObject first = JsonObjectUtil.packJsonObject(day, "#EED016");
            //今天的时间
            resultMap.put("first", first);
            logger.info("first:{}", first);
            try {
                //处理天气
                WeatherNowBO weatherNowBO = tianqiService.getNowWeather();
                //城市
                JSONObject city = JsonObjectUtil.packJsonObject("彭州市", "#60AEF2");
                resultMap.put("city", city);
                logger.info("city:{}", city);
                //天气
                JSONObject weather = JsonObjectUtil.packJsonObject(weatherNowBO.getText(), "#b28d0a");
                resultMap.put("weather", weather);
                logger.info("weather:{}", weather);
                //最低气温
                JSONObject minTemperature = JsonObjectUtil.packJsonObject(weatherNowBO.getDew() + "°", "#0ace3c");
                resultMap.put("minTemperature", minTemperature);
                logger.info("minTemperature:{}", minTemperature);
                //最高气温
                JSONObject maxTemperature = JsonObjectUtil.packJsonObject(weatherNowBO.getTemp() + "°", "#dc1010");
                resultMap.put("maxTemperature", maxTemperature);
                logger.info("maxTemperature:{}", maxTemperature);
                //风
                JSONObject wind = JsonObjectUtil.packJsonObject(weatherNowBO.getWindDir() + "," + weatherNowBO.getWindSpeed(), "#6e6e6e");
                resultMap.put("wind", wind);
                logger.info("wind:{}", wind);
                //湿度
                JSONObject wet = JsonObjectUtil.packJsonObject(weatherNowBO.getHumidity(), "#1f95c5");
                resultMap.put("wet", wet);
                logger.info("wet:{}", wet);
                //未来三天天气
                Map<String, String> map = tianqiService.getTheNextThreeDaysWeather();
                if (map.isEmpty()) {
                    logger.info("三天的天气获取失败");
                }
                JSONObject day1_wea = JsonObjectUtil.packJsonObject(map.get("今"), WxHelper.isContainsRain(map.get("今")));
                JSONObject day2_wea = JsonObjectUtil.packJsonObject(map.get("明"), WxHelper.isContainsRain(map.get("明")));
                JSONObject day3_wea = JsonObjectUtil.packJsonObject(map.get("后"), WxHelper.isContainsRain(map.get("后")));
                resultMap.put("day1_wea", day1_wea);
                resultMap.put("day2_wea", day2_wea);
                resultMap.put("day3_wea", day3_wea);
                logger.info("day1_wea:{}、{}、{}", day1_wea, day2_wea, day3_wea);
                JSONObject message = JsonObjectUtil.packJsonObject(configConstant.getMessage(), "#000000");
                resultMap.put("message", message);
            } catch (Exception e) {
                logger.error("天气获取失败: {}", ExceptionUtil.stacktraceToString(e));
                HashMap<String, Object> map = new HashMap<>();
                map.put("天气获取错误", "检查apiSpace配置的token正确与否");
                errorList.add(new JSONObject(map));
                throw new RuntimeException("天气获取失败");
            }


            //生日，升级——>支持农历生日啦
            try {
                JSONObject birthDate1;
                JSONObject birthDate2;

                if (configConstant.getLunarSwitch()) {
                    birthDate1 = LunarCalendar.getLunarBirthday(configConstant.getBirthday1());
                    birthDate2 = LunarCalendar.getLunarBirthday(configConstant.getBirthday2());
                } else {
                    birthDate1 = WxHelper.getBirthday(configConstant.getBirthday1(), date);
                    birthDate2 = WxHelper.getBirthday(configConstant.getBirthday2(), date);

                }
                resultMap.put("birthDate1", birthDate1);
                logger.info("birthDate1:{}", birthDate1)
                ;
                resultMap.put("birthDate2", birthDate2);
                logger.info("birthDate2:{}", birthDate2);
            } catch (Exception e) {
                throw new RuntimeException("生日处理失败");
            }

            //在一起时间
            try {
                JSONObject togetherDate = wxHelper.togetherDay(date);
                resultMap.put("togetherDate", togetherDate);
                logger.info("togetherDate:{}", togetherDate);
            } catch (Exception e) {
                throw new RuntimeException("在一起时间处理失败");
            }
            //名言警句，判断有没开启每日一句功能，application.yaml可以配置~
            if (configConstant.isEnableDaily() && StringUtils.hasText(configConstant.getToken())) {
                //名言警句,中文
                String noteZh = null;
                try {
                    noteZh = proverbService.getOneNormalProverb();
                    JSONObject note_Zh = JsonObjectUtil.packJsonObject(noteZh, "#879191");
                    resultMap.put("note_Zh", note_Zh);
                    logger.info("note_Zh:{}", note_Zh);
                } catch (Exception e) {
                    logger.info("名言警句获取失败，检查ApiSpace的token是否正确？套餐是否过期？");
                }
                //名言警句，英文
                try {
                    JSONObject note_En = JsonObjectUtil.packJsonObject(proverbService.translateToEnglish(noteZh), "#879191");
                    resultMap.put("note_En", note_En);
                    logger.info("note_En:{}", note_En);
                } catch (Exception e) {
                    logger.info("名言警句翻译失败，网易云翻译接口无法使用");
                }
            }
            //封装数据并发送
            templateMsg = wxHelper.sendMessage(accessToken, errorList, resultMap, opedId);
        }
        JSONObject result = new JSONObject();
        if (!errorList.isEmpty()) {
            result.put("result", "信息推送失败！");
            result.put("errorData", errorList);
        } else {
            result.put("result", "信息推送成功！");
            result.put("请求结构体", templateMsg);
            logger.info("信息推送成功！");
        }
        return result.toJSONString();
    }

    /**
     * 处理微信后台发过来的文本，属高级功能，教程没给不用管
     *
     * @param request
     * @param response
     * @return
     */
    @Override
    public String messageHandle(HttpServletRequest request, HttpServletResponse response) {
        response.setCharacterEncoding("utf-8");
        Map<String, String> resultMap = MessageUtil.parseXml(request);
        TextMessage textMessage = new TextMessage();
        textMessage.setToUserName(resultMap.get("FromUserName"));
        textMessage.setFromUserName(resultMap.get("ToUserName"));
        Date date = new Date();
        textMessage.setCreateTime(date.getTime());
        textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);

        if ("text".equals(resultMap.get("MsgType"))) {
            textMessage.setContent(resultMap.get("Content"));
        } else {
            textMessage.setContent("目前仅支持文本呦");
        }
        return textMessage.getContent();
    }

    @Override
    public String sendQyWeChatMsg() {
        String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + qyWxHelper.getQyWxAccessToken();

        QyWxImageTextMessage imageTextMessage = qyWxHelper.createImageTextMessage();

        // imageTextMessage.getTemplate_card().getMain_title().setDesc("今日天气");

        imageTextMessage.getTemplate_card().getImage_text_area().setTitle(StrUtil.format("♥在一起♥: 第{}天啦", DateUtil.betweenDay(DateUtil.parseDate(configConstant.getTogetherDate()), DateUtil.date(), true)));
        if (configConstant.getLunarSwitch()) {
            imageTextMessage.getTemplate_card().getImage_text_area().setDesc(StrUtil.format("蛋娃生日：{}天，六娃生日{}天", LunarCalendar.getLunarBirthdayDay(configConstant.getBirthday1()), LunarCalendar.getLunarBirthdayDay(configConstant.getBirthday2())));
        } else {
            imageTextMessage.getTemplate_card().getImage_text_area().setDesc(StrUtil.format("蛋娃生日：{}天，六娃生日{}天", WxHelper.getBirthdayDay(configConstant.getBirthday1(), DateUtil.today()), WxHelper.getBirthdayDay(configConstant.getBirthday2(), DateUtil.today())));
        }

        //名言警句，判断有没开启每日一句功能，application.yaml可以配置~
        if (configConstant.isEnableDaily() && StringUtils.hasText(configConstant.getToken())) {
            //名言警句,中文
            String noteZh = null;
            try {
                noteZh = proverbService.getOneNormalProverb();
                logger.info("note_Zh:{}", noteZh);
                imageTextMessage.getTemplate_card().setQuote_area(QyWxImageTextMessage.TemplateCardBean.QuoteAreaBean.builder()
                        .type(QyWxClickEnum.NONE.getClick())
                        .title(noteZh)
                        .build());
            } catch (Exception e) {
                logger.info("名言警句获取失败，检查ApiSpace的token是否正确？套餐是否过期？");
            }
            //名言警句，英文
            try {
                String note_En = proverbService.translateToEnglish(noteZh);
                logger.info("note_En:{}", note_En);
                imageTextMessage.getTemplate_card().getQuote_area().setQuote_text(note_En);
            } catch (Exception e) {
                logger.info("名言警句翻译失败，网易云翻译接口无法使用");
                imageTextMessage.getTemplate_card().getQuote_area().setQuote_text(noteZh);
            }
        }

        // {彭州}：{多云} 温度：{15}°C {12~20°C} {东南风}({3-5}级 {8}公里/小时)
        String titleTemplate1 = "{}:{} {}°C({}~{}°C) {}({}级 {}km/h)";
        // {8点}：{多云} 温度：{15}°C {东南风}({3-5}级 {8}公里/小时)\n // ======= 8点 11点 13点 17点 18点 ======== //
        String descTemplate1 = "{}时:{} {}°C {}({}级 {}km/h)\n";
        WeatherNowBO nowWeather = tianqiService.getNowWeather();
        List<WeatherThreeDayBO> threeDaysWeatherList = tianqiService.getTheNextThreeDaysWeatherList();
        List<WeatherHourlyBO> weather24hList = tianqiService.get24hWeatherList();
        for (WeatherHourlyBO hourlyBO : weather24hList) {
            hourlyBO.setFxTime(StrUtil.sub(DateUtil.format(DateUtil.parse(hourlyBO.getFxTime(), "yyyy-MM-dd'T'HH:mmXXX"), DatePattern.PURE_TIME_PATTERN), 0, 2));
        }
        Map<String, WeatherHourlyBO> weatherHourlyBOMap = weather24hList.stream().collect(Collectors.toMap(WeatherHourlyBO::getFxTime, item -> item));
        WeatherHourlyBO hourly08 = weatherHourlyBOMap.get("08");
        WeatherHourlyBO hourly11 = weatherHourlyBOMap.get("11");
        WeatherHourlyBO hourly13 = weatherHourlyBOMap.get("13");
        WeatherHourlyBO hourly17 = weatherHourlyBOMap.get("17");
        WeatherHourlyBO hourly18 = weatherHourlyBOMap.get("18");
        QyWxImageTextMessage.TemplateCardBean.VerticalContentListBean verticalContentList1 = QyWxImageTextMessage.TemplateCardBean.VerticalContentListBean.builder()
                .title(StrUtil.format(titleTemplate1
                        , configConstant.getCityDesc(), nowWeather.getText()
                        , nowWeather.getTemp(), threeDaysWeatherList.get(0).getTempMin(), threeDaysWeatherList.get(0).getTempMax()
                        , nowWeather.getWindDir(), nowWeather.getWindScale(), nowWeather.getWindSpeed())
                )
                .desc(
                        StrUtil.format(descTemplate1, "08", hourly08.getText(), hourly08.getTemp(), hourly08.getWindDir(), hourly08.getWindScale(), hourly08.getWindSpeed())
                                + StrUtil.format(descTemplate1, "1 1", hourly11.getText(), hourly11.getTemp(), hourly11.getWindDir(), hourly11.getWindScale(), hourly11.getWindSpeed())
                                + StrUtil.format(descTemplate1, "1 3", hourly13.getText(), hourly13.getTemp(), hourly13.getWindDir(), hourly13.getWindScale(), hourly13.getWindSpeed())
                                + StrUtil.format(descTemplate1, "1 7", hourly17.getText(), hourly17.getTemp(), hourly17.getWindDir(), hourly17.getWindScale(), hourly17.getWindSpeed())
                                + StrUtil.format(descTemplate1, "1 8", hourly18.getText(), hourly18.getTemp(), hourly18.getWindDir(), hourly18.getWindScale(), hourly18.getWindSpeed())
                )
                .build();
        // {未来两日天气}：☀️{2024-11-18} ☀️{2024-11-19}
        String titleTemplate2 = "{}\n☀️{}☀️{}☀️";
        // {2024-11-18}\n天气：{多云}\n温度：{15}~{25}°C\n风向：{东南风}({3-5}级 {8}公里/小时)\n夜间风力：{}级\n降水量：{}\n // ======= 8点 11点 13点 17点 18点 ======== //
        String descTemplate2 = "天气：{}\n温度：{}°C\n风向：{}\n夜间风力：{}级\n降水量：{}mm\n";
        WeatherThreeDayBO weatherTomorrow_1 = threeDaysWeatherList.get(1);
        WeatherThreeDayBO weatherTomorrow_2 = threeDaysWeatherList.get(2);
        QyWxImageTextMessage.TemplateCardBean.VerticalContentListBean verticalContentList2 = QyWxImageTextMessage.TemplateCardBean.VerticalContentListBean.builder()
                .title(StrUtil.format(titleTemplate2
                        , configConstant.getCityDesc() + "未来两日天气", DateUtil.formatDate(DateUtil.tomorrow()), DateUtil.formatDate(DateUtil.offsetDay(DateUtil.date(), 2)))
                )
                .desc(
                        StrUtil.format(descTemplate2
                                , weatherTomorrow_1.getTextDay() + StrUtil.COMMA + StrUtil.SPACE + weatherTomorrow_2.getTextDay()
                                , weatherTomorrow_1.getTempMin() + "~" + weatherTomorrow_1.getTempMax() + "°C" + StrUtil.COMMA + StrUtil.SPACE + weatherTomorrow_2.getTempMin() + "~" + weatherTomorrow_2.getTempMax()
                                , weatherTomorrow_1.getWindDirDay() + "(" + weatherTomorrow_1.getWindScaleDay() + "级 " + weatherTomorrow_1.getWindSpeedDay() + "km/h)" + StrUtil.COMMA + StrUtil.SPACE + weatherTomorrow_2.getWindDirDay() + "(" + weatherTomorrow_2.getWindScaleDay() + "级 " + weatherTomorrow_2.getWindSpeedDay() + "km/h)"
                                , weatherTomorrow_1.getWindScaleNight() + "级" + StrUtil.COMMA + StrUtil.SPACE + weatherTomorrow_2.getWindScaleNight()
                                , weatherTomorrow_1.getPrecip() + "mm" + StrUtil.COMMA + StrUtil.SPACE + weatherTomorrow_2.getPrecip())
                )
                .build();
        // 家人生日 老二生日：{}天\n老弟生日：{}天\n爸(自贡)生日：{}天\n妈(自贡)生日：{}天\n爸(广元)生日：{}天\n妈(广元)生日：{}天\外爷生日：{}天\n姐姐生日：{}天\n哥哥生日：{}天\n露露生日：{}天\n菲菲生日：{}天\n
        String descTemplate3 = "{}：{}天";
        List<String> birthdayList = CollUtil.newArrayList();
        BirthdateEnum.getBirthdayMap().forEach((key, value) -> birthdayList.add(StrUtil.format(descTemplate3, key, value)));
        QyWxImageTextMessage.TemplateCardBean.VerticalContentListBean verticalContentList3 = QyWxImageTextMessage.TemplateCardBean.VerticalContentListBean.builder()
                .title("🍰🍰🍰家人生日🍰🍰🍰")
                .desc(
                        StrUtil.join("\n", birthdayList)
                )
                .build();
        imageTextMessage.getTemplate_card().setVertical_content_list(CollUtil.newArrayList(verticalContentList1, verticalContentList2, verticalContentList3));

        String jsonStr = JSONUtil.toJsonStr(imageTextMessage, JSONConfig.create());
        logger.info("sendMsg: {}", jsonStr);
        return HttpUtils.sendPost(url, jsonStr);
    }
}






























